package data.email;

import data.Statistic;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * EmailStatistic adalah statistik yang dimiliki oleh sebuah term dalam dokumen
 * email
 *
 * @author Robert Gunawan
 */
public class EmailStatistic implements Statistic {

    public static String from = "from";
    public static String to = "to";
    public static String subject = "subject";
    public static String date = "date";
    public static String body = "body";

    @Override
    public String getTermString() {
        return termString;
    }

    /**
     * menambahkan related document ke dalam email statistic
     *
     * @param label label term
     * @param docID document id
     * @param positions array posisi term dalam label
     */
    public void addRelatedDoc(String label, Integer docID, ArrayList<Integer> positions) {
        HashMap<Integer, ArrayList<Integer>> relatedDocs = ((EmailDocumentStatistic) statistics.get(label)).getRelatedDocs();
        if (relatedDocs.containsKey(docID)) {
            ((ArrayList<Integer>) relatedDocs.get(docID)).addAll(positions);
        } else {
            relatedDocs.put(docID, positions);
        }
    }

    /**
     * mendapatkan document statistic untuk label yang diberikan
     *
     * @param label label dari term
     * @return email document statistic
     */
    public EmailDocumentStatistic getDocStatistic(String label) {
        return (EmailDocumentStatistic) this.statistics.get(label);
    }

    /**
     * email document statistic adalah kelas untuk menampung related documents
     * dari sebuah term untuk label tertentu, email document statistic memiliki
     * sebuah hash map yang memetakan document ID dengan array of position dari
     * term dalam label
     */
    static public class EmailDocumentStatistic implements Serializable {

        /**
         * related documents
         */
        private HashMap<Integer, ArrayList<Integer>> relatedDocuments;

        @Override
        public String toString() {
            String temp = "";
            Iterator it = relatedDocuments.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry pairs = (Map.Entry) it.next();
                temp += "{ " + (Integer) pairs.getKey() + ", ";
                temp += (ArrayList<Integer>) pairs.getValue() + " }";
            }
            return temp;
        }

        /**
         * konstruktor dari email document statistic
         */
        public EmailDocumentStatistic() {
            relatedDocuments = new HashMap<Integer, ArrayList<Integer>>();
        }

        /**
         * mendapatkan related docs
         *
         * @return related docs
         */
        public HashMap<Integer, ArrayList<Integer>> getRelatedDocs() {
            return relatedDocuments;
        }

        /**
         * menambahkan sebuah posisi term dalam document
         *
         * @param documentID ID dari document
         * @param position posisi dari term
         */
        public void addPos(Integer documentID, Integer position) {
            if (relatedDocuments.containsKey(documentID)) {
                ((ArrayList<Integer>) relatedDocuments.get(documentID)).add(position);
            } else {
                ArrayList<Integer> positions = new ArrayList<Integer>();
                positions.add(position);
                relatedDocuments.put(documentID, positions);
            }
        }

        /**
         * menggabungkan posting list dari satu document email statistic lain
         *
         * @param anotherStatistic email document statistic lain
         */
        public void merge(EmailDocumentStatistic anotherStatistic) {
            HashMap<Integer, ArrayList<Integer>> mp = anotherStatistic.getRelatedDocs();
            Iterator it = mp.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry pairs = (Map.Entry) it.next();
                Integer docID = (Integer) pairs.getKey();
                ArrayList<Integer> positions = (ArrayList<Integer>) pairs.getValue();

                if (!relatedDocuments.containsKey(docID)) {
                    // tambahkan indeks dan related documents
                    relatedDocuments.put(docID, positions);
                } else {
                    // sudah ada, merge positions
                    ArrayList<Integer> currPost = (ArrayList<Integer>) relatedDocuments.get(docID);
                    for (Integer pos : positions) {
                        if (!currPost.contains(pos)) {
                            currPost.add(pos);
                        }
                    }
                    relatedDocuments.put(docID, currPost);
                }
            }
        }
    }
    /**
     * koleksi email document statistic untuk tiap label
     */
    private HashMap<String, EmailDocumentStatistic> statistics;
    /**
     * term string
     */
    private String termString;

    @Override
    public String toString() {
        String temp = "\n";
        temp += "from : " + statistics.get(from).toString() + "\n";
        temp += "to: " + statistics.get(to).toString() + "\n";
        temp += "date : " + statistics.get(date).toString() + "\n";
        temp += "body : " + statistics.get(body).toString() + "\n";
        temp += "subject : " + statistics.get(subject).toString() + "\n";
        return temp;
    }

    /**
     * konstruktur dari email statistic, menginisialisasi statistic untuk tiap
     * label dalam email
     *
     * @param termString term string
     */
    public EmailStatistic(String termString) {
        this.termString = termString;
        statistics = new HashMap<String, EmailDocumentStatistic>();
        statistics.put(from, new EmailDocumentStatistic());
        statistics.put(to, new EmailDocumentStatistic());
        statistics.put(date, new EmailDocumentStatistic());
        statistics.put(body, new EmailDocumentStatistic());
        statistics.put(subject, new EmailDocumentStatistic());
    }

    @Override
    public void merge(Statistic anotherStatistic) {
        try {
            EmailStatistic statistic = (EmailStatistic) anotherStatistic;
            ((EmailDocumentStatistic) statistics.get(from)).merge(statistic.getDocStatistic(from));
            ((EmailDocumentStatistic) statistics.get(to)).merge(statistic.getDocStatistic(to));
            ((EmailDocumentStatistic) statistics.get(body)).merge(statistic.getDocStatistic(body));
            ((EmailDocumentStatistic) statistics.get(date)).merge(statistic.getDocStatistic(date));
            ((EmailDocumentStatistic) statistics.get(subject)).merge(statistic.getDocStatistic(subject));
        } catch (Exception ex) {
        }
    }

    @Override
    public void preCheck() {
    }

    @Override
    public void postCheck() {
    }
}
